﻿using System;
using System.Configuration;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.XPath;

namespace Catalyst.Configuration
{
	public class ConfigurationSectionHandler : IConfigurationSectionHandler
	{
		#region IConfigurationSectionHandler Members

		public object Create(object parent, object configContext, XmlNode section)
		{
			// get the name of the type from the type= attribute on the root node
			XPathNavigator navigator = section.CreateNavigator();

			string typeName = navigator.Evaluate("string(@type)").ToString();
			
			if (typeName == string.Empty)
			{
				throw new ConfigurationException(String.Format("The type attribute is not present on the root node of the <{0}> configuration section ", section.Name), section);
			}

			// make sure this string evaluates to a valid type
			Type type = Type.GetType(typeName);

			if (type == null)
			{
				throw new ConfigurationException(String.Format("The type attribute \"{0}\" specified in the root node of the <{1}> configuration section is not a valid type", typeName, section.Name), section);
			}

			XmlSerializer serializer = new XmlSerializer(type);

			// attempt to deserialize an object of this type from the provided XML section

			XmlNodeReader reader = new XmlNodeReader(section);

			try
			{
				return serializer.Deserialize(reader);
			}
			catch (Exception ex)
			{
				string s = ex.Message;
				Exception innerException = ex.InnerException;

				do
				{
					s += " " + innerException.Message;

					innerException = innerException.InnerException;
				}
				while (ex.InnerException != null);

				throw new ConfigurationException(String.Format("Unable to deserialize an object of type \"{0}\" from the <{1}> configuration section: {2}", typeName, section.Name, s), ex, section);
			}
		}

		#endregion
	}
}
